// 不写作泛型了,直接让队列存储String
class MyBlockingQueue{
    // 此处也可以使用构造方法,来指定数组的最大长度
    private String[] data = new String[1000];
    // 队列的起始位置
    // 都加上volatile,防止出现内存可见性问题
    private volatile int head = 0;
    // 队列的结束位置的下一个位置
    private volatile int tail = 0;
    // 队列中的有效元素个数
    private volatile int size = 0;

    // 入队列和出队列
    public void put(String elem) throws InterruptedException {
        synchronized (this) {
            while (size == data.length) {
                // 满了,再插入就阻塞了
                // 普通队列,直接return
                this.wait();
            }
            data[tail] = elem;
            tail++;
            // 如果自增之后来到了数组末尾,让它回到数组的开头,环形队列
            if (tail == data.length) {
                tail = 0;
            }
            size++;
            // 这个notify用来唤醒take中的wait
            this.notify();
        }
    }

    public String take() throws InterruptedException {
        synchronized (this) {
            while (size == 0) {
                // 队列为空,直接返回
                // 队列为空,继续出队列就会出现阻塞
                this.wait();
            }

            String ret = data[head];
            head++;
            size--;
            if (head == data.length) {
                head = 0;
            }
            // 这个notify用来唤醒put中的wait
            this.notify();
            return ret;
        }
    }
}
public class Demo23 {
    public static void main(String[] args) {
        // 生产者和消费者分别用一个线程来表示(也可以用多个)

        MyBlockingQueue queue = new MyBlockingQueue();

        // 消费者
        Thread t1 = new Thread(()->{
            while(true){
                try {
                    String result = queue.take();
                    System.out.println("消费元素 = " + result);

                    Thread.sleep(500);
                    // 先不sleep,利用sleep控制生产和消费的速度
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });

        // 生产者
        Thread t2 = new Thread(()->{
            int num = 1;
           while(true) {
               try {
                   queue.put(num + " ");
                   System.out.println("生产元素 = " + num);
                   num++;

                   // Thread.sleep(500);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }

           }
        });

        t1.start();
        t2.start();
    }
}